﻿using System;
using System.Collections.Generic;
using System.Text;

namespace CSModeling
{
    partial class SMFModel
    {
        class Matrix3D
        {
            public Double[,] M3D = new Double[4, 4];

            public Matrix3D()
            {
                for (int i = 0; i < 4; i++)
                    M3D[i, i] = 1;
            }
            public Matrix3D(Double[,] matrixSet)
            {
                for (int i = 0; i < 4; i++)
                    for (int j = 0; j < 4; j++)
                        this.M3D[i, j] = matrixSet[i, j];
            }
                        public static Matrix3D operator *(Matrix3D matrix1, Matrix3D matrix2)
            {
                Matrix3D res = new Matrix3D();
                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        res.M3D[i, j] = 0;
                        for (int k = 0; k < 4; k++)
                        {
                            res.M3D[i, j] += matrix1.M3D[i, k] * matrix2.M3D[k, j];
                        }
                    }
                }
                return res;

            }
            public static Vector3D operator *(Matrix3D matrix, Vector3D point)
            {
                Vector3D res = new Vector3D();
                for (int i = 0; i < 4; i++)
                {
                    Double k = 0;
                    for (int j = 0; j < 4; j++)
                    {
                        k += (matrix.M3D[j, i] * point.getList(j));
                    }
                    res.setList(i, k);
                }
                return res;
            }
            public static Matrix3D Reverse(Matrix3D matrix)
            {
                //double[,] res = Matrix3DMath.ReverseMatrix(matrix.M3D, 4);
                //if (res == null)
                    return null;
                //else
                    //return new Matrix3D(res);
            }

        }

        class Matrix3DMath
        {
            public static Matrix3D T(Double Tx, Double Ty, Double Tz)
            //平移变换
            {
                Matrix3D res = new Matrix3D();
                for (int i = 0; i < 4; i++)
                    res.M3D[i, i] = 1;
                res.M3D[3, 0] = Tx; res.M3D[3, 1] = Ty; res.M3D[3, 2] = Tz;
                return res;
            }
            public static Matrix3D S(Double Sx, Double Sy, Double Sz)
            //放缩变换
            {
                Matrix3D res = new Matrix3D();
                res.M3D[0, 0] = Sx; res.M3D[1, 1] = Sy; res.M3D[2, 2] = Sz;
                return res;
            }
            public static Matrix3D ViewMatrix()
            {
                return Matrix3DMath.T(250, 200, 100);

            }
            public static Matrix3D ReversedViewMatrix()
            {
                return Matrix3DMath.T(-250, -200, -100);
            }
            public static Matrix3D RotateX(Double thet)
            {
                Matrix3D res = new Matrix3D();
                res.M3D[0, 0] = 1; res.M3D[3, 3] = 1;
                res.M3D[1, 1] = Math.Cos(thet); res.M3D[2, 2] = res.M3D[1, 1];
                res.M3D[1, 2] = Math.Sin(thet); res.M3D[2, 1] = res.M3D[1, 2] * (-1);
                return res;

            }
            public static Matrix3D RotateY(Double thet)
            {
                Matrix3D res = new Matrix3D();
                res.M3D[1, 1] = 1; res.M3D[3, 3] = 1;
                res.M3D[0, 0] = Math.Cos(thet); res.M3D[3, 3] = res.M3D[0, 0];
                res.M3D[2, 0] = Math.Sin(thet); res.M3D[0, 2] = res.M3D[2, 0] * (-1);
                return res;

            }
            public static Matrix3D RotateZ(Double thet)
            {
                Matrix3D res = new Matrix3D();
                res.M3D[2, 2] = 1; res.M3D[3, 3] = 1;
                res.M3D[0, 0] = Math.Cos(thet); res.M3D[1, 1] = res.M3D[0, 0];
                res.M3D[0, 1] = Math.Sin(thet); res.M3D[1, 0] = res.M3D[0, 1] * (-1);
                return res;

            }
            public static Double DEGtoRAD(Double DEG)
            {
                return (DEG / 180 * Math.PI);
            }
            private static double[,] ReverseMatrix(double[,] dMatrix, int Level)
            {
                double dMatrixValue = MatrixValue(dMatrix, Level);
                if (dMatrixValue == 0) return null;
                double[,] dReverseMatrix = new double[Level, 2 * Level];
                double x, c;
                for (int i = 0; i < Level; i++)
                {
                    for (int j = 0; j < 2 * Level; j++)
                    {
                        if (j < Level)
                            dReverseMatrix[i, j] = dMatrix[i, j];
                        else
                            dReverseMatrix[i, j] = 0;
                    }
                    dReverseMatrix[i, Level + i] = 1;
                }
                for (int i = 0, j = 0; i < Level && j < Level; i++, j++)
                {
                    if (dReverseMatrix[i, j] == 0)
                    {
                        int m = i;
                        for (; dMatrix[m, j] == 0; m++) ;
                        if (m == Level)
                            return null;
                        else
                        {
                            for (int n = j; n < 2 * Level; n++)
                                dReverseMatrix[i, n] += dReverseMatrix[m, n];
                        }
                    }
                    x = dReverseMatrix[i, j];
                    if (x != 1)
                    {
                        for (int n = j; n < 2 * Level; n++)
                            if (dReverseMatrix[i, n] != 0)
                                dReverseMatrix[i, n] /= x;
                    }
                    for (int s = Level - 1; s > i; s--)
                    {
                        x = dReverseMatrix[s, j];
                        for (int t = j; t < 2 * Level; t++)
                            dReverseMatrix[s, t] -= (dReverseMatrix[i, t] * x);
                    }
                }
                for (int i = Level - 2; i >= 0; i--)
                {
                    for (int j = i + 1; j < Level; j++)
                        if (dReverseMatrix[i, j] != 0)
                        {
                            c = dReverseMatrix[i, j];
                            for (int n = j; n < 2 * Level; n++)
                                dReverseMatrix[i, n] -= (c * dReverseMatrix[j, n]);
                        }
                }
                double[,] dReturn = new double[Level, Level];
                for (int i = 0; i < Level; i++)
                    for (int j = 0; j < Level; j++)
                        dReturn[i, j] = dReverseMatrix[i, j + Level];
                return dReturn;
            }
            private static double MatrixValue(double[,] MatrixList, int Level)
            {
                double[,] dMatrix = new double[Level, Level];
                for (int i = 0; i < Level; i++)
                    for (int j = 0; j < Level; j++)
                        dMatrix[i, j] = MatrixList[i, j];
                double c, x;
                int k = 1;
                for (int i = 0, j = 0; i < Level && j < Level; i++, j++)
                {
                    if (dMatrix[i, j] == 0)
                    {
                        int m = i;
                        for (; dMatrix[m, j] == 0; m++) ;
                        if (m == Level)
                            return 0;
                        else
                        {

                            for (int n = j; n < Level; n++)
                            {
                                c = dMatrix[i, n];
                                dMatrix[i, n] = dMatrix[m, n];
                                dMatrix[m, n] = c;
                            }
                            k *= (-1);
                        }
                    }
                    for (int s = Level - 1; s > i; s--)
                    {
                        x = dMatrix[s, j];
                        for (int t = j; t < Level; t++)
                            dMatrix[s, t] -= dMatrix[i, t] * (x / dMatrix[i, j]);
                    }
                }
                double sn = 1;
                for (int i = 0; i < Level; i++)
                {
                    if (dMatrix[i, i] != 0)
                        sn *= dMatrix[i, i];
                    else
                        return 0;
                }
                return k * sn;
            }
        }
    }
}
